﻿using System;
using System.Collections.Generic;
using System.Text;
using OutLook = Microsoft.Office.Interop.Outlook;
using System.IO;

namespace GoogleSync
{
    class OutContact : AContact
    {

        static OutLook.Application app;

        OutLook.ContactItem outlookContact;

        public OutContact(OutLook.MAPIFolder folder, OutLook.Application myApp)
        {
            app = myApp;
            registerCalls();
            outlookContact = (OutLook.ContactItem)folder.Items.Add(OutLook.OlItemType.olContactItem);
        }

        public OutContact(OutLook.ContactItem outlookContact, OutLook.Application myApp)
        {
            app = myApp;
            registerCalls();
            this.outlookContact = outlookContact;
        }

        private void registerCalls()
        {
            getFields.Add(Fields.FIRST, delegate
            {
                return getFirstName();
            });

            setFields.Add(Fields.FIRST, delegate(String value)
            {
                setFirstName(value);
            });

            getFields.Add(Fields.MIDDLE, delegate
            {
                return outlookContact.MiddleName;
            });

            setFields.Add(Fields.MIDDLE, delegate(String value)
            {
                outlookContact.MiddleName = value;
            });

            getFields.Add(Fields.LAST, delegate
            {
                return getLastName();
            });

            setFields.Add(Fields.LAST, delegate(String value)
            {
                setLastName(value);
            });

            getFields.Add(Fields.TITLE, delegate
            {
                return getTitleName();
            });

            setFields.Add(Fields.TITLE, delegate(String value)
            {
                setTitleName(value);
            });

            getFields.Add(Fields.NICKNAME, delegate
            {
                return outlookContact.NickName;
            });

            setFields.Add(Fields.NICKNAME, delegate(String value)
            {
                outlookContact.NickName = value;
            });

            getFields.Add(Fields.COMPANY, delegate
            {
                return outlookContact.CompanyName;
            });

            setFields.Add(Fields.COMPANY, delegate(String value)
            {
                outlookContact.CompanyName = value;
            });

            getFields.Add(Fields.OTHER_PHONE, delegate
            {
                return outlookContact.OtherTelephoneNumber;
            });

            setFields.Add(Fields.OTHER_PHONE, delegate(String value)
            {
                outlookContact.OtherTelephoneNumber = value;
            });

            getFields.Add(Fields.BUSINESS_PHONE, delegate
            {
                return outlookContact.BusinessTelephoneNumber;
            });

            setFields.Add(Fields.BUSINESS_PHONE, delegate(String value)
            {
                outlookContact.BusinessTelephoneNumber = value;
            });

            getFields.Add(Fields.BUSINESS_PHONE2, delegate
            {
                return outlookContact.Business2TelephoneNumber;
            });

            setFields.Add(Fields.BUSINESS_PHONE2, delegate(String value)
            {
                outlookContact.Business2TelephoneNumber = value;
            });

            getFields.Add(Fields.MOBILE_PHONE, delegate
            {
                return outlookContact.MobileTelephoneNumber;
            });

            setFields.Add(Fields.MOBILE_PHONE, delegate(String value)
            {
                outlookContact.MobileTelephoneNumber = value;
            });

            getFields.Add(Fields.MOBILE_PHONE2, delegate
            {
                return outlookContact.PagerNumber;
            });

            setFields.Add(Fields.MOBILE_PHONE2, delegate(String value)
            {
                outlookContact.PagerNumber = value;
            });

            getFields.Add(Fields.HOME_PHONE, delegate
            {
                return outlookContact.HomeTelephoneNumber;
            });

            setFields.Add(Fields.HOME_PHONE, delegate(String value)
            {
                outlookContact.HomeTelephoneNumber = value;
            });

            getFields.Add(Fields.HOME_PHONE2, delegate
            {
                return outlookContact.Home2TelephoneNumber;
            });

            setFields.Add(Fields.HOME_PHONE2, delegate(String value)
            {
                outlookContact.Home2TelephoneNumber = value;
            });

            getFields.Add(Fields.EMAIL1, delegate
            {
                return outlookContact.Email1Address;
            });

            setFields.Add(Fields.EMAIL1, delegate(String value)
            {
                outlookContact.Email1Address = value;
            });

            getFields.Add(Fields.EMAIL2, delegate
            {
                return outlookContact.Email2Address;
            });

            setFields.Add(Fields.EMAIL2, delegate(String value)
            {
                outlookContact.Email2Address = value;
            });

            getFields.Add(Fields.EMAIL3, delegate
            {
                return outlookContact.Email3Address;
            });

            setFields.Add(Fields.EMAIL3, delegate(String value)
            {
                outlookContact.Email3Address = value;
            });

            getFields.Add(Fields.BUSINESS_ADDR, delegate
            {
                return translateCrLf(outlookContact.BusinessAddress);
            });

            setFields.Add(Fields.BUSINESS_ADDR, delegate(String value)
            {
                outlookContact.BusinessAddress = translateLf(value);
            });

            getFields.Add(Fields.HOME_ADDR, delegate
            {
                return translateCrLf(outlookContact.HomeAddress);
            });

            setFields.Add(Fields.HOME_ADDR, delegate(String value)
            {
                outlookContact.HomeAddress = translateLf(value);
            });

            getFields.Add(Fields.OUTID, delegate
            {
                return getOutlookContactID();
            });

            setFields.Add(Fields.OUTID, delegate(String value)
            {
            });

        }

        private static String translateCrLf(String trans)
        {
            return trans == null ? "" : trans.Replace("\r\n", "\n");
        }

        private static String translateLf(String trans)
        {
            return trans == null ? "" : trans.Replace("\n", "\r\n");
        }

        public String getOutlookContactID()
        {
            return outlookContact.EntryID;
        }

        public String getFirstName()
        {
            return outlookContact.FirstName;
        }

        public void setFirstName(String name)
        {
            outlookContact.FirstName = name;
        }

        public String getLastName()
        {
            return outlookContact.LastName;
        }

        public String getTitleName()
        {
            return outlookContact.Title;
        }

        public void setLastName(String name)
        {
            outlookContact.LastName = name;
        }

        public void setTitleName(String name)
        {
            outlookContact.Title = name;
        }

        public override void save()
        {
            if (changed)
            {
                outlookContact.Save();
                changed = false;
            }
        }

        private byte[] pictureBytes = null;

        private String pictureHash = null;

        public override byte[] getPictureBytes(String lastEtag)
        {
            getPictureHash();
            return pictureBytes;
        }

        public override String getPictureHash()
        {
            if (pictureHash != null)
                return pictureHash;
            pictureHash = "";
            foreach (OutLook.Attachment attachment in outlookContact.Attachments)
            {
                String contentId = attachment.DisplayName;
                if (contentId.StartsWith("ContactP"))
                {
                    String tempFile = ContactSync.HOME + "temp.jpg";
                    if (File.Exists(tempFile))
                        File.Delete(tempFile);
                    attachment.SaveAsFile(tempFile);
                    pictureBytes =
                       File.ReadAllBytes(tempFile);
                    pictureHash = getHashFromBytes(pictureBytes);
                    String file = ContactSync.HOME + pictureHash + ".jpg";
                    if (File.Exists(file))
                        File.Delete(file);
                    File.Move(tempFile, file);
                }
            }
            return pictureHash;
        }

        public override void delete()
        {
            outlookContact.Delete();
        }

        public override void setPictureBytes(byte[] bytes)
        {
            if (bytes == null)
                return;
            Console.WriteLine("Changing picture for: " + outlookContact.FullName);
            changed = true;
            this.pictureBytes = null;
            this.pictureHash = null;
            outlookContact.RemovePicture();
            int i = outlookContact.Attachments.Count;
            while (i > -1 && outlookContact.Attachments.Count > 0)
            {
                outlookContact.Attachments.Remove(--i);
            }
            outlookContact.Save();
            String tempFile = ContactSync.HOME + "outtemp.jpg";
            File.WriteAllBytes(tempFile, bytes);
            outlookContact.AddPicture(tempFile);
            File.Delete(tempFile);
            outlookContact.Save();

        }
    }
}
